package structure;

import java.util.ArrayList;

public class parsingTable {

	private ArrayList<String> row;
	private ArrayList<String> col;
	private ArrayList<String[]> connection;
	private ArrayList<ArrayList<String>> table;
	private powerset powerset;
	
	
	public parsingTable(powerset powerset){
		
		this.row= new ArrayList<String>();
		this.col= new ArrayList<String>();
		this.connection= powerset.getConnection();
		this.table= new ArrayList<ArrayList<String>>();
		this.powerset= powerset;
		
		this.createRowCol();
		
		this.createParsingTable();
	}

	//get
	public int getRowIndex(String s){
		
		for(int k=0; k<this.row.size(); k++){
			
			if(s.equals(this.row.get(k))){
				
				return k;
			}
		}
		
		return -1;
	}
	
	public int getColIndex(String s){
		
		for(int k=0; k<this.col.size(); k++){
			
			if(s.equals(this.col.get(k))){
				
				return k;
			}
		}
		
		return -1;
	}
	
	public powerset getPowerset(){
		
		return this.powerset;
	}
	
	public ArrayList<ArrayList<String>> getTable(){
		
		return this.table;
	}
	//
	
	//set
	
	//
	
	//crea la parsing table
	private void createParsingTable(){
		
		//aggiungo gli shift e go to
		for(String[] s : this.connection){
			
			int row= this.getRowIndex(s[0]);
			String arc= s[1];
			int col= this.getColIndex(s[1]);
			String dest= s[2];
			if(this.table.get(row).get(col).equals(" ")){

				//arco con terminale aggiungo sh q0
				if(this.powerset.getEnumGrammar().getVT().contains(arc)){
					this.table.get(row).set(col, "sh "+dest);
				}
				//arco con non terminale aggiungo q0
				else if(this.powerset.getEnumGrammar().getVN().contains(arc)){
					this.table.get(row).set(col, dest);
				}
			}
			else{
				System.out.println("ERROR(sh e go to): La grammatica non è una grammatica LR(1).");
				break;
			}
		}
		
		//aggiungo per lo stato finale acc
		for(state st : this.powerset.getStates()){
			
			if(st.isFinal()){
				
				item item= st.getItems().get(0);
				
				String look= item.getLookahead().get(0);
				
				int col= this.getColIndex(look);
				int row= this.getRowIndex(st.getLabel());
				
				if(this.table.get(row).get(col).equals(" "))
					this.table.get(row).set(col, "acc");
				else{
					System.out.println("ERROR(accept): La grammatica non è una grammatica LR(1).");
					break;
				}
			}
		}
		
		//aggiungo le reduce
		for(state st : this.powerset.getStates()){
			
			if(!st.isFinal()){
				ArrayList<item> items= st.getItems();
				for(item i : items){
					
					if(i.isComplete()){
						
						ArrayList<String> lookahead= i.getLookahead();
						//prendo il numero della produzione che produce quell'item
						String rightsideClean= i.getRightside();
						if(rightsideClean.equals(".")){
							rightsideClean= "e";
						}
						else{
							rightsideClean= rightsideClean.substring(0, rightsideClean.lastIndexOf("."));
						}
						//System.out.println(rightsideClean);
						int index= this.powerset.getEnumGrammar().getIndexByRightside(rightsideClean);
						for(String l : lookahead){
							
							int row= this.getRowIndex(st.getLabel());
							int col= this.getColIndex(l);
							//System.out.println("row= "+ row + "col= " + col + " l= " + l);
							if(this.table.get(row).get(col).equals(" "))
								this.table.get(row).set(col, "red "+index);
							else{
								System.out.println("ERROR(reduce): La grammatica non è una grammatica LR(1).");
								break;
							}
						}
					}
				}
			}
				
		}
	}
	
	//crea le righe e le colonne
	private void createRowCol(){

		for(state st : this.powerset.getStates()){
			
			if(!this.row.contains(st.getLabel())){
				
				this.row.add(st.getLabel());
			}
		}
		
		int index= 0;
		for(String s : this.powerset.getEnumGrammar().getVT()){

			if(!this.col.contains(s) && !s.equals("e")){

				this.col.add(s);
				index++;
			}
		}
		
		this.col.add("$");
		index++;

		for(String s : this.powerset.getEnumGrammar().getVN()){
			
			if(!this.col.contains(s) && !s.equals("e")){
				
				this.col.add(s);
				index++;
			}
		}
		
		for(String s : this.row){

			
			ArrayList<String> toAdd= new ArrayList<String>();
			for(int i=0; i<index; i++){
				toAdd.add(" ");
			}
			this.table.add(toAdd);
		}
	}
	
	public void printItAll(){
		
		System.out.print("\t");
		for(String s : this.col){
			System.out.print(s + " | ");
		}
		
		System.out.println("");
		
		for(int k=0; k<this.table.size(); k++){
			
			System.out.println(this.row.get(k) + " | " + this.table.get(k));
		}
		/*
		for(String s : this.row){
			System.out.println(s + " | ");
		}
		
		System.out.println("table= " + this.table);*/
	}
}
